# 这个模块主要用来决定一个区块中不同的载物，以及他们是如何验证合法性的、如何签名（如果需要的话）
# 这里统一一下如下的接口规则,不同的规则以前缀和后缀加以区分(例如event_submit和trans_submit以及contr_submit，后缀则主要用来在验证方式上下功夫)：
# submit(self, **kwargs): 提交一次事件, 后续的参数根据不同的情景需要是变长的，但是为了统一接口，因此整成定长的**kargs形式
# verify(self, **kwargs): 验证一次事件，可以是白验证，也可以是签名的验证等等

# TODO：0.0 代码编写

from collections import OrderedDict
from globalVariables import MINING_SENDER
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA
import binascii


def trans_submit(self, **kwargs):
    """
        transaction的输入应该为一个形如
        {
            "sender_address":
            "recipient_address":
            "value":
            "signature":(如果使用白验证则应该为空)
        }
        提交一次交易
        Add a transaction to transactions array if the signature verified
    """
    transaction = OrderedDict({'sender_address': kwargs["sender_address"],
                               'recipient_address': kwargs["recipient_address"],
                               'value': kwargs["value"]})

    # Reward for mining a block
    # 挖矿奖励
    if kwargs["sender_address"] == MINING_SENDER:
        self.transactions.append(transaction)
        return len(self.chain) + 1
    # Manages transactions from wallet to another wallet
    else:
        # TODO:这里可能要改，至少在区块是空验证的时候这里的形式是否还需要保留可能要在代码实践中讨论
        transaction_verification = self.verify_transaction_signature({
                                                                "sender_address": kwargs["sender_address"],
                                                                "signature": kwargs["signature"],
                                                                "transaction": transaction})
        if transaction_verification:
            self.transactions.append(transaction)
            return len(self.chain) + 1
        else:
            return False


def trans_verify_white(self, **kwargs):
    '''
    白验证：无论什么情况都返回真
    '''
    return True


def trans_verify_signature(self, **kwargs):
    '''
    :param kwargs: 这里的输入应该形如：
    {
        "sender_address":
        "signature":
        "transaction":
    }
    :return: 交易是否合法
    '''

    public_key = RSA.importKey(binascii.unhexlify(kwargs["sender_address"]))
    verifier = PKCS1_v1_5.new(public_key)
    h = SHA.new(str(kwargs["transaction"]).encode('utf8'))
    return verifier.verify(h, binascii.unhexlify(kwargs["signature"]))
